home *** CD-ROM | disk | FTP | other *** search
Text File | 1989-04-25 | 3.5 KB | 152 lines | [TEXT/MPS ] |
- (*
- A simple unit that demonstrates how to produce asynchronous sound with
- the Macintosh Sound Manager. Although I am pretty confident about this code,
- I don't guarantee that this code demonstrates the correct way to do things. It
- does seem to work reliably.
-
- This unit doesn't solve any of the tricky issues about using the Sound Manager.
- Primarily, sound channels should be disposed of as soon as they are no longer
- needed. This code does just that, but it doesn't prevent your program or a
- background program from trying to make sound.
-
- Changes:
-
- 2/16/89 Lock the sound resource; state restored in call back;
- gSoundPlaying is the actual handle.
- 3/24/89 IsSoundPlaying disposes of the channel when done.
-
- Larry Rosenstein
- Apple Computer, Inc.
-
- © Copyright 1988, 1989 Apple Computer Inc. All Rights Reserved.
- *)
-
-
- UNIT UAsynchSnd;
-
- INTERFACE
-
- USES
- MemTypes, Quickdraw, OSIntf, ToolIntf;
-
- { call this before any other routine }
- PROCEDURE InitUAsynchSnd;
-
- { returns TRUE if an asynchronous sound is playing }
- FUNCTION IsSoundPlaying: BOOLEAN;
-
- { equivalent to SndPlay, but does it asynchronously; if you call this
- while another sound is playing, the first one will be stopped }
- FUNCTION AsynchSndPlay(sndHandle: Handle): OSErr;
-
- { stop the sound from playing; may be called even if no sound is
- currently playing }
- PROCEDURE StopAsynchSound;
-
- { should be called when your program exits }
- PROCEDURE TerminateUAsynchSnd;
-
- IMPLEMENTATION
-
- VAR
- gSoundPlaying: Handle;
- gSoundState: SignedByte;
- gSndChannel: SndChannelPtr;
-
- PROCEDURE ChanCallBack(chan: SndChannelPtr; cmd: SndCommand); FORWARD;
- FUNCTION GetA5: LONGINT; INLINE $2E8D; {MOVE.L A5,(A7)}
- FUNCTION LoadA5(newA5: LONGINT): LONGINT;
- INLINE $2F4D,$0004,$2A5F;
-
- (********************)
-
- PROCEDURE InitUAsynchSnd;
- BEGIN
- gSndChannel := NIL;
- gSoundPlaying := NIL;
- END;
-
-
- FUNCTION AsynchSndPlay(sndHandle: Handle): OSErr;
- VAR err: OSErr;
- aCommand: SndCommand;
-
- BEGIN
- StopAsynchSound; { kill the current sound & channel }
-
- err := noErr; { default value }
-
- { gSndChannel should be NIL now }
- err := SndNewChannel(gSndChannel, 0, 0, @ChanCallBack);
- { We don't specify a synthesizer, since we are assuming that
- the snd resource specifies one. For example, the
- standard Clink-Klank snd resource doesn't use the
- sampled synthesizer. }
-
- gSoundState := HGetState(sndHandle);
- MoveHHi(sndHandle);
- HLock(sndHandle);
- gSoundPlaying := sndHandle;
-
- IF err = noErr THEN
- err := SndPlay(gSndChannel, sndHandle, TRUE);
-
- WITH aCommand DO BEGIN
- cmd := callBackCmd;
- param1 := 0;
- param2 := GetA5;
- END;
- IF err = noErr THEN
- err := SndDoCommand(gSndChannel, aCommand, FALSE);
-
- IF err <> noErr THEN
- StopAsynchSound; { flush channel; unlock sound }
-
- AsynchSndPlay := err;
- END;
-
-
- PROCEDURE ChanCallBack(chan: SndChannelPtr; cmd: SndCommand);
- VAR oldA5: LONGINT;
- BEGIN
- oldA5 := LoadA5(cmd.param2); { get the application's A5 and set it }
-
- HSetState(gSoundPlaying, gSoundState);
- gSoundPlaying := NIL;
-
- oldA5 := LoadA5(oldA5); { restore old A5 }
- END;
-
-
- FUNCTION IsSoundPlaying: BOOLEAN;
- VAR result: BOOLEAN;
-
- BEGIN
- result := gSoundPlaying <> NIL;
- IF NOT result then
- StopAsynchSound; { to dispose of channel }
- IsSoundPlaying := result;
- END;
-
-
- PROCEDURE StopAsynchSound;
- BEGIN
- IF gSndChannel <> NIL THEN BEGIN
- IF SndDisposeChannel(gSndChannel, TRUE) = noErr THEN { nothing };
- gSndChannel := NIL;
- END;
- IF gSoundPlaying <> NIL THEN
- BEGIN
- HSetState(gSoundPlaying, gSoundState);
- gSoundPlaying := NIL;
- END;
- END;
-
- PROCEDURE TerminateUAsynchSnd;
- BEGIN
- StopAsynchSound;
- END;
-
-
- END.
-